<template>
  <!-- 面包屑导航
        separator: 分隔符/
   -->
  <el-breadcrumb class="app-breadcrumb" separator="/">
    <!-- vue内置动画组件: transition-group 每个子标签必须有key动画才生效 -->
    <!-- name属性设置过渡效果名字, 会自动添加一些类名, 我们只需要实现对应类名的css具体代码 -->
    <transition-group name="breadcrumb">
      <!-- V-for循环面包屑导航项    key 是 面包屑对应的路由路径 -->
      <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
        <!--   插槽自定义面包屑item的显示内容
        当前面包屑对应的路由对象没有redirect 或者 此项是最后一个,就显示span标签
        面包屑的文字是路由规则对象的meta中的title属性下 -->
        <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
        <!-- 如果不是最后一项, 是左边的面包屑带a标签, 可以点击 -->
        <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
      </el-breadcrumb-item>
    </transition-group>
  </el-breadcrumb>
</template>

<script>
import pathToRegexp from 'path-to-regexp'

export default {
  data() {
    return {
      levelList: null // 面包屑项  数组(路由对象的)
    }
  },
  watch: {
    $route() {
      this.getBreadcrumb()
    }
    // watch可以监听data里和computed里定义属性变量
    // 说全: watch可以侦听this组件对象里的属性 (this.$route)
    // 所以watch可以侦听$route路由对象的改变
    // 当前组件不重新加载, 但是路由改变了, 此函数会执行
    // 白: 当路由变化, 重新计算面包屑导航
  },
  created() {
    this.getBreadcrumb()
  },
  methods: {
    getBreadcrumb() {
      // only show routes with meta.title
      // 拿到仅仅带meta.title值的路由对象
      // this.$route.matched: 拿到当前路由页面, 所有"相关的"路由规则对象合成的数组(在路径上)
      // 例如: 路径: #/example/table
      // matched值: [{path:'/example'}, {path: '/examplte/table'}]
      let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
      const first = matched[0] // 取出第一个

      if (!this.isDashboard(first)) {
        // 是为了让面包屑导航, 第一个一直是首页的意思
        matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched)
      }
      // 是否有meta.title, 而且meta.breadcrumb属性值
      this.levelList = matched.filter(item =>
        item.meta && item.meta.title && item.meta.breadcrumb !== false) // item.meta.breadcrumb ->undefined
      // undefined(隐式判断为false, 0, '', null)
      // 三等要考虑类型, 虽然你有隐式转换, 但是类型不同...
      // 所以 undefined !== false 为 true
      //  这个值为true
    },
    // 当前路由对象, 是不是dashboard, 如果是返回true, 否则返回false
    isDashboard(route) {
      const name = route && route.name
      if (!name) {
        return false
      }
      // 如果你有name, 把name去除空格转成小写字母, 和'dashborad'对比, 如果是一样, 返回true
      return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
    },
    // 把params参数里值, 填充到动态路径中
    // 例如: params: {id: 10001, num: 10}
    // 例如: 路由规则对象path是: /upload/:num/:id
    // 此方法返回 /upload/10/10001
    pathCompile(path) {
      // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
      const { params } = this.$route // 提取路由路径上参数和值
      var toPath = pathToRegexp.compile(path)
      return toPath(params)
    },
    handleLink(item) {
      const { redirect, path } = item // 提取重定向路径, 正常此项路由路径
      if (redirect) {
        this.$router.push(redirect) // 如果有重定向优先调走
        return
      }
      this.$router.push(this.pathCompile(path)) // 带路径值跳转路由
    }
  }
}
</script>

<style lang="scss" scoped>
.app-breadcrumb.el-breadcrumb {
  display: inline-block;
  font-size: 14px;
  line-height: 50px;
  margin-left: 8px;

  .no-redirect {
    color: #97a8be;
    cursor: text;
  }
}
</style>
